package t735

import (
	"errors"
	"strconv"
	"strings"
)

type MyStack struct {
	items []int
	//l     sync.Mutex
}

func (m *MyStack) Push(n int) {
	//m.l.Lock()
	//defer m.l.Unlock()
	m.items = append(m.items, n)
}

func (m *MyStack) Pop() (int, error) {
	//m.l.Lock()
	//defer m.l.Unlock()
	if len(m.items) == 0 {
		return 0, errors.New("empty of stack")
	}
	el := m.items[len(m.items)-1]
	m.items = m.items[:len(m.items)-1]
	return el, nil
}

func (m *MyStack) Top() (int, error) {
	//m.l.Lock()
	//defer m.l.Unlock()
	if len(m.items) == 0 {
		return 0, errors.New("empty of stack")
	}
	el := m.items[len(m.items)-1]
	return el, nil
}

func (m *MyStack) Size() int {
	return len(m.items)
}

func (m *MyStack) Empty() bool {
	if len(m.items) == 0 {
		return true
	}
	return false
}

func (m *MyStack) Clear() {
	m.items = m.items[0:0]
}

func (m *MyStack) String() string {
	tmp := make([]string, len(m.items))
	for _, item := range m.items {
		tmp = append(tmp, strconv.Itoa(item))
	}
	return strings.Join(tmp, " ")
}

func asteroidCollision(asteroids []int) []int {

	stack := &MyStack{}
	// -2, 1, -2, -2

	for _, num := range asteroids {

		top, err := stack.Top()
		if err != nil {

			stack.Push(num)
			//fmt.Println(stack)
			continue
		}
		if top < 0 {
			stack.Push(num)
		} else {
			if num < 0 {
				if top+num == 0 {
					_, _ = stack.Pop()
				} else if top+num > 0 {
					continue
				} else {
					_, _ = stack.Pop()
					// 循环往前碰撞
				Loop:
					for {
						forTop, err := stack.Top()
						if err != nil {
							stack.Push(num)
							break Loop
						}
						if forTop < 0 {
							stack.Push(num)
							//fmt.Println("stack2", stack)
							break Loop
						}
						if forTop+num == 0 {
							_, _ = stack.Pop()
							break Loop
						} else if forTop+num > 0 {
							break Loop
						} else {
							_, _ = stack.Pop()
							continue
						}
					}

				}
			} else {
				stack.Push(num)
			}
		}
	}

	return stack.items
}
